package com.example.design.ddd.practice2.domain.order.entity;

import cn.hutool.core.lang.ObjectId;
import com.example.design.ddd.practice2.common.DomainEventPublisher;
import com.example.design.ddd.practice2.domain.Payment.entity.Payment;
import com.example.design.ddd.practice2.domain.order.OrderStatus;
import com.example.design.ddd.practice2.domain.order.event.OrderPaidEvent;
import com.example.design.ddd.practice2.domain.order.valueobject.Address;
import com.example.design.ddd.practice2.domain.order.valueobject.Money;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Currency;
import java.util.List;

/**
 * 聚合根 - 订单
 * 包含订单业务逻辑
 */
public class Order {
    private String orderId;
    private String userId;
    private List<OrderItem> items = new ArrayList<>();
    private Address address;
    private OrderStatus status;
    private LocalDateTime createdAt;
    private Money money;

    /**
     * 领域方法 - 创建订单
     *
     * @param userId
     * @param items
     * @param address
     * @return
     */
    public static Order create(String userId, List<OrderItem> items, Address address) {
        Order order = new Order();
        order.orderId = ObjectId.next();
        order.userId = userId;
        order.items = new ArrayList<>(items);
        order.address = address;
        order.status = OrderStatus.CREATED;
        order.createdAt = LocalDateTime.now();
        validateOrder(order);

        Currency currency = null;
        BigDecimal amount = BigDecimal.ZERO;
        for (OrderItem item : items) {
            Money itemMoney = item.total();
            currency = itemMoney.getCurrency();
            amount = amount.add(itemMoney.getAmount());
        }
        order.money = new Money(amount, currency);
        return order;
    }

    /**
     * 领域方法 - 支付订单
     */
    public void pay(Payment payment) {
        if (status != OrderStatus.CREATED) {
            throw new IllegalStateException("订单状态异常");
        }
        if (!payment.validate()) {
            throw new IllegalArgumentException("支付信息无效");
        }
        this.status = OrderStatus.PAID;
        DomainEventPublisher.publish(new OrderPaidEvent(this.orderId, this.money));
    }

    /**
     * 校验订单
     * @param order
     */
    private static void validateOrder(Order order) {
        if (order.items == null || order.items.isEmpty()) {
            throw new IllegalArgumentException("订单必须包含商品");
        }
    }

    public String getOrderId() {
        return orderId;
    }

    public List<OrderItem> getItems() {
        return items;
    }

}
